package com.basic.juc;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * locate com.basic.juc
 * Created by 79875 on 2017/10/7.
 * 模拟CAS算法 原子性操作
 */
//public class TestCompareAndSwap {
//    public static void main(String[] args) {
//        final CompareAndSwap compareAndSwap=new CompareAndSwap();
//        final int[] count = {0};
//        for(int i=0;i<20;i++)
//            new Thread(new Runnable() {
//                @Override
//                public void run() {
//                    int exepctvaule = compareAndSwap.get();
//                    boolean b=compareAndSwap.compareAndSet(exepctvaule,(int)(Math.random()*101));
//                    System.out.println(b);
//
//                }
//            }).start();
//        System.out.println("一共进行尝试的次数"+count[0]);
//    }
//}

/**
 * 这个类主要对于上面的模拟CAS算法进行改进，使用原子类AtomicInteger来代替synchronized关键字。
 * 来进行记录一共尝试的次数。
 * 一共尝试多少次能够完成开辟20个线程进行cas的操作,经过测试是大于20的,确实是有线程并发的情况,
 * 并使用自旋的方式来进行确保cas的正确执行
 */
public class TestCompareAndSwap {
    public static void main(String[] args) {
        final CompareAndSwap compareAndSwap = new CompareAndSwap();
        AtomicInteger count = new AtomicInteger(0);  // 用AtomicInteger
        for (int i = 0; i < 20; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    int oldValue, newValue;
                    newValue = (int)(Math.random() * 101);
                    do {
                        oldValue = compareAndSwap.get();
                        count.incrementAndGet(); // 原子加1
                        System.out.println("1");
                    } while (!compareAndSwap.compareAndSet(oldValue, newValue));
                }
            }).start();
        }

        // 等待一下线程结束再打印，不然主线程太快
        try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
        System.out.println("一共进行尝试的次数 " + count.get());
    }
}
class CompareAndSwap{
    private int value;

    /**
     * 获取内存值
     * @return
     */
    public  synchronized  int get(){
        return value;
    }

    /**
     * 比较
     * @param expectValue
     * @param newVaule
     * @return
     */
    public synchronized int compareAndSwap(int expectValue, int newVaule){
        int oldValue=value;
        if(oldValue==expectValue){
            value=newVaule;
        }
        return oldValue;
    }

    /**
     * 设置
     * @param expectValue
     * @param newVaule
     * @return
     */
    public synchronized boolean compareAndSet(int expectValue, int newVaule){
        return expectValue == compareAndSwap(expectValue,newVaule);
    }
}
